package dfl.bysj.service.impl;

import com.aliyun.oss.model.GetObjectRequest;
import com.aliyun.oss.model.ListObjectsRequest;
import com.aliyun.oss.model.ObjectListing;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.zxing.WriterException;
import dfl.bysj.config.OssProperties;
import dfl.bysj.config.QRCodeGenerator;
import dfl.bysj.config.RedisKey;
import dfl.bysj.entity.Floor;
import dfl.bysj.entity.HonestStudent;
import dfl.bysj.entity.Seat;
import dfl.bysj.entity.VO.Form_value;
import dfl.bysj.entity.VO.SeatVO;
import dfl.bysj.exception.UnifiedException;
import dfl.bysj.mapper.SeatMapper;
import dfl.bysj.result.ResponseEnum;
import dfl.bysj.service.FileService;
import dfl.bysj.service.FloorService;
import dfl.bysj.service.SeatService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import dfl.bysj.service.SeatStateService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.servlet.ServletOutputStream;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author DFL
 * @since 2022-05-17
 */
@Slf4j
@Service
public class SeatServiceImpl extends ServiceImpl<SeatMapper, Seat> implements SeatService {
    private RedisTemplate redisTemplate;

    private FloorService floorService;

    private SeatStateService seatStateService;

    private FileService fileService;

    private SeatMapper seatMapper;

    @Autowired
    public void setSeatMapper(SeatMapper seatMapper) {
        this.seatMapper = seatMapper;
    }

    @Autowired
    public void setFileService(FileService fileService) {
        this.fileService = fileService;
    }

    @Autowired
    public void setSeatStateService(SeatStateService seatStateService) {
        this.seatStateService = seatStateService;
    }

    @Autowired
    public void setFloorService(FloorService floorService) {
        this.floorService = floorService;
    }

    @Autowired
    public void setRedisTemplate(RedisTemplate redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    private List<Seat> seats;

    private AtomicReference<Seat> seatAtomicReference = new AtomicReference<>(new Seat());


    private void getSeats() {
        seats = (List<Seat>) redisTemplate.opsForValue().get(RedisKey.ALL_SEAT);
        if (seats == null) {
            updateRedisOfSeats();

        }
    }

    private void updateRedisOfSeats() {
        seats = list();
        redisTemplate.opsForValue().set(RedisKey.ALL_SEAT, seats, 7, TimeUnit.DAYS);
    }


    @Override
    public List<SeatVO> getAllSeatVO() {
        getSeats();
        List<SeatVO> seatVOS = new ArrayList<>();
        seats.stream()
                .forEach(s -> {
                    SeatVO seatVO = new SeatVO(s,
                            floorService.getFloorByfloId(s.getFloId()),
                            seatStateService.getAllSeatStateVOBySeaId(s.getSeaId()));
                    //判断座位状态
                    seatVO.setSeatStateComment(seatStateService.getStateName(s.getSeaId()));
                    seatVOS.add(seatVO);

                });
        return seatVOS;
    }

    @Override
    public void insertSeat(Form_value form_value) {
        Thread thread=new Thread(()->{
            List<Seat> list = new ArrayList<>();
            int seaNum = getMaxNumByFloId(form_value.getFloId());
            Seat newSeatId = getOne(new QueryWrapper<Seat>()
                    .orderByDesc("sea_id")
                    .last("limit 1"));
            for (int i = 0; i < form_value.getSeatCount(); i++) {
                list.add(new Seat(++seaNum, form_value.getFloId()));
            }
            saveBatch(list);
            updateRedisOfSeats();
        });
       thread.start();
       try {
           thread.join();
       }catch (Exception e){
           throw new UnifiedException(ResponseEnum.ERROR);
       }
       //获取最新的座位id
        List<Seat> seatList=seatMapper.selectList(new QueryWrapper<Seat>()
                .orderByDesc("update_time")
                .last("limit "+form_value.getSeatCount()));
        //新增状态
        seatStateService.insertSeatStatesByResSta(seatList, form_value.getReserveState());
    }

    @Override
    public void generateQRCode() {
        //获取所有的座位id检测谁没有就给谁造
        getSeats();
        seats.stream()
                .filter(s -> s.getSeaCrcode() == null || s.getSeaCrcode().equals(""))
                .forEach(s -> {
                    try {
                        byte[] bytes = QRCodeGenerator.getQRCodeImage(String.valueOf(s.getSeaId()), 300, 300);
                        InputStream inputStream = new ByteArrayInputStream(bytes);
                        Floor floor = floorService.getFloorByfloId(s.getFloId());

                        String picName = String.valueOf(floor.getFloNum()) + "楼" + String.valueOf(s.getSeaNum()) + "号";
                        String fileName = fileService.upload(inputStream, "QRCode", picName);

                        //将访问路径传回数据库
                        s.setSeaCrcode(fileName);
                        update(s, new QueryWrapper<Seat>()
                                .eq("sea_id", s.getSeaId()));
                    } catch (WriterException e) {
                        throw new RuntimeException(e);
                    } catch (IOException e) {
                        throw new RuntimeException(e);
                    }
                });
        updateRedisOfSeats();
    }

    private void deleteAllQRCode() {

        getSeats();
        seats.stream()
                .forEach(s->{
                    fileService.removeFile(s.getSeaPicture());
                });
    }

    @Override
    public void download(ServletOutputStream outputStream) {
        fileService.download(outputStream, "QRCode");
    }

    @Override
    public List<String> getAllQRCodeName() {
//        return "https://" + OssProperties.BUCKET_NAME + "." + OssProperties.ENDPOINT + "/" + key;
//        key:QRCode
        //文件名（服务器上的文件路径）
        String host = "https://" + OssProperties.BUCKET_NAME + "." + OssProperties.ENDPOINT + "/";
        getSeats();
        List<String> list = new ArrayList<>();
        seats.stream()
                .filter(s -> s.getSeaCrcode() != null)
                .forEach(s -> {
                    String url = s.getSeaCrcode();
                    String objectName = url.substring(host.length());
                    list.add(objectName);
                });
        return list;
    }

    private int getMaxNumByFloId(Integer floId) {
        getSeats();
        AtomicInteger max = new AtomicInteger(1);
        seats.stream()
                .filter(s -> s.getFloId().equals(floId))
                .forEach(s -> {
                    if (s.getSeaNum() > max.get()) {
                        max.set(s.getSeaNum());
                    }
                });
        return max.get();
    }
}
